/** @file main.c
* Main entry point into the vxp utility. Does the following:
* @li Parses command line arguments
* @li Initializes MemBlock
* @li Initializes Flex and yyscanner
* @li Scans the XPath string given as an argument to the program
* @li Parses the tokens generates by Flex
* @li Prints the XPath Syntax Tree
* @li Cleans up and exits
*
* main() is needed to run the app.
* vxpExit() is needed to perform cleanup (see errors.c).
* @author Victor Petrov <victor_petrov@harvard.edu>
* @date   Feb 26, 2011
* @see main()
* @see vxpExit()
* @cond
*------------------------------------------------------------------------------
* LEGAL:
*------------------------------------------------------------------------------
*
* Copyright (c) 2011, The President and Fellows of Harvard College
* Copyright (c) 2011, The Neuroinformatics Research Group at Harvard University
* All rights reserved.
*
* License: New BSD License   <http://creativecommons.org/licenses/BSD/>
*-------------------------
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions are met:
*
*	Redistributions of source code must retain the above copyright notice, 
*	this list of conditions and the following disclaimer.
*
*	Redistributions in binary form must reproduce the above copyright notice, 
*	this list of conditions and the following disclaimer in the documentation
*	and/or other materials provided with the distribution.
*
*	Neither the name of the Neuroinformatics Research Group at Harvard, nor 
*	the names of its contributors may be used to endorse or promote products 
*	derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
* POSSIBILITY OF SUCH DAMAGE.
*------------------------------------------------------------------------------
* vim: ts=4
*------------------------------------------------------------------------------
* @endcond
*/

#include <stdio.h>      /* printf(), fprintf() */
#include <string.h>     /* strcmp(); */
#include "ast.h"        /* struct Node */
#include "printers.h"   /* printXPath() */
#include "vxp-state.h"	/* struct vxpState */

/*****************
* (evil) GLOBALS *
*****************/

/** XPath version to use when printing the AST.
* @see enum XPathVersion
*/
static enum XPathVersion printVersion=XPATH_10;

/** Format to use when printing the AST.
* @see enum PrintFormat
*/
static enum PrintFormat  printFormat=PRINT_TEXT;

/** The XPath string to be scanned and parsed. */
static char* xpathString=NULL;

/** An internal Flex structure, required by re-entrant scanners and parsers.
* @see vxp_lex_init()
*/
static void* yyscanner=NULL;

/** Flex user defined variables are stored in a vxpState struct
* @see struct vxpState
*/
struct vxpState* state=NULL;

/************
* FUNCTIONS *
************/

/** Frees all memory, cleans up and calls exit().
* Also called by function handling fatal errors in errors.c .
* @param[in] mem    The MemBlockInfo struct to free
* @param[in] status Exit code to pass to exit()
* @see errors.c
* @warning This function will always terminate the program.
*/
void vxpExit(struct MemBlockInfo* mem, int status);

/** Parses command line arguments.
* @param[in] argc Number of command line arguments
* @param[in] argv An array of argument values
*/
static void parseArguments(int argc, char* argv[]);

/** Displays the help page.
* @param[in] out    Either stdout or stderr
* @param[in] status Exit code
* @param[in] argc   Number of command line arguments
* @param[in] argv   An array of argument values
*/
static void showHelp(FILE* out, int status, int argc, char* argv[]);


/**************************************
*  Flex and Bison generated functions *
**************************************/

/**
*  @name Functions Generated by Flex / Bison
*  @{
*/

/** Flex initialization function
* @param[in] yyscanner Pointer to an internal Flex struct
* @return    0 on Success, non-zero on Failure
*/
extern int vxp_lex_init_extra(struct vxpState* state, void** yyscanner);

/** Flex function to scan a NUL-terminated string
* @param[in] str       The string to be scanned
* @param[in] yyscanner An internal Flex struct
* @return    int       YY_BUFFER_STATE
* @warning This function contains 2 underscores after 'vxp'.
*/
extern int vxp__scan_string(const char* str, void* yyscanner);

/** Flex clean-up function
* @param[in] yyscanner An internal Flex struct
* @return    0 on Success, non-zero on Failure
*/
extern int vxp_lex_destroy(void* yyscanner);

/** Bison function to start parsing the tokens 
* @param[in]  yyscanner An internal Flex struct
* @param[out] root      Root of the generated Syntax Tree
* @param[in]  mem       An initialized MemBlockInfo struct
* @return     0 on Success, non-zero on Failure
*/
extern int vxp_parse(void* yyscanner, struct Node** root, 
                     struct MemBlockInfo* mem);


/**@}*/

/** Main entry point into vxp. Performs the following:
* @li Parses command line arguments
* @li Initializes MemBlock
* @li Initializes Flex and yyscanner
* @li Scans the XPath string given as an argument to the program
* @li Parses the tokens generates by Flex
* @li Prints the XPath Syntax Tree
* @li Cleans up and exits
*
* @param[in] argc Number of command line arguments
* @param[in] argv An array of argument values
*/
int main(int argc, char* argv[])
{
	struct Node* root;                /* AST root node */
    struct MemBlockInfo* mem=NULL;    /* MemBlockInfo struct for the tree */
    int result=0;                     /* stores results from functions */

	parseArguments(argc,argv);        /* Check command line arguments */
	if (!xpathString)                 /* Verify required parameter */
	{
		fprintf(stderr,"ERROR: Please supply an XPath 1.0 expression.\n");
        showHelp(stderr, EXIT_FAILURE,argc,argv);
	}

    mem=memInit(sizeof(struct Node)); /* Tell MemBlock what we want to alloc */
    if (!mem)                         /* Check for errors */
    {
        fprintf(stderr,"ERROR: Unable to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

	initState(&state,mem);

    result=vxp_lex_init_extra(state,&yyscanner);  /* Initialize Flex */
    if (result)                       /* Check for errors */
    {
        fprintf(stderr,"ERROR: Failed to initialize lexer. (E%d)\n",result);
        exit(result);
    }

    vxp__scan_string(xpathString, yyscanner);       /* Scan the XPath string */
    vxp_parse(yyscanner, &root, mem);               /* Parse the tokens */
    printXPath(root,printFormat,printVersion,mem);  /* Print the result AST */
	vxpExit(mem,EXIT_SUCCESS);                      /* Clean up and exit */

	return EXIT_SUCCESS;                            /* Satisfies "int main()"*/
}


/** Frees all memory, cleans up and calls exit()
* @param[in] mem    The MemBlockInfo struct to free
* @param[in] status Exit code to pass to exit()
* @see errors.c
* @warning This function will always terminate the program.
*/
void vxpExit(struct MemBlockInfo* mem, int status)
{
	free(state);				/* Free user defined Flex data */
	vxp_lex_destroy(yyscanner); /* Tell Flex to clean up */
    memFree(mem);               /* Free memory allocated for the AST */
	exit(status);               /* Exit the program */
}

/** Parses command line arguments.
* @param[in] argc Number of command line arguments
* @param[in] argv An array of argument values
*/
static void parseArguments(int argc, char* argv[])
{
	int i=0;

	if (argc<=1)                            /* No parameters? */
		return;                             /* Nothing to parse */

	for (i=1;i<argc;i++)                    /* Iterate over all arguments */
	{
		if (strcmp(argv[i],"--xpath10")==0) /* --xpath10 */
			printVersion=XPATH_10;
		else
		if (strcmp(argv[i],"--xpath20")==0) /* --xpath20 */
			printVersion=XPATH_20;
		else
		if (strcmp(argv[i],"--xpath21")==0) /* --xpath21 */
			printVersion=XPATH_21;
        else
        if (strcmp(argv[i],"--text")==0)    /* --text */
            printFormat=PRINT_TEXT;
        else
        if (strcmp(argv[i],"--table")==0)   /* --table */
            printFormat=PRINT_TABLE;
		else
        if (strcmp(argv[i],"--xml")==0)     /* --xml */
            printFormat=PRINT_XML;
		else
        if (strcmp(argv[i],"--help")==0)    /* --help */
            showHelp(stdout,EXIT_SUCCESS, argc,argv);            
        else
			xpathString=argv[i];            /* set the XPath string to parse */
	}
}

/** Displays the help page.
* @param[in] out    Either stdout or stderr
* @param[in] status Exit code
* @param[in] argc   Number of command line arguments
* @param[in] argv   An array of argument values
*/
static void showHelp(FILE* out, int status, int argc, char* argv[])
{
    fprintf(out,"vxp v1.0 - an XPath 1.0 parser\n\n");
    fprintf(out,"Usage: %s [OPTIONS] <xpath>\n\n",argv[0]);
    fprintf(out,"Options:\n");
    fprintf(out,"\t--table    Print tree as a table (useful for testing)\n");
    fprintf(out,"\t--text     Print tree nodes indented (default)\n");
    fprintf(out,"\t--xml      Print tree nodes as indented XML\n");
    fprintf(out,"\t--xpath10  Print XPath 1.0 compatible tree (default)\n");
    fprintf(out,"\t--xpath20  Print XPath 2.0 comptabile tree (N/A)\n");
    fprintf(out,"\t--xpath21  Print XPath 2.1 comptabile tree\n");
    fprintf(out,"\n");
    fprintf(out,"Author: Victor Petrov <victor_petrov@harvard.edu>\n");
    exit(status);
}

